﻿// Copyright 2013 Ronald Schlenker, www.technewlogic.de.
// 
// This file is part of Byond.
// 
// Byond is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 2 of the License, or
// (at your option) any later version.
// 
// Byond is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// along with Byond.  If not, see <http://www.gnu.org/licenses/>.
using System;
using Byond.AudioMidi;
using Byond.HostObjects;
using Byond.Messages;
using Byond.Midi;

namespace Byond
{
	public sealed class MidiCallbackManager : IDisposable
	{
		private readonly IMidi _midi;

		private readonly CallbackControllerCache _callbackControllerCache = new CallbackControllerCache();

		private readonly CallbackController<NoteOnMessage> _noteOnController = new CallbackController<NoteOnMessage>();
		internal CallbackController<NoteOnMessage> NoteOnController { get { return _noteOnController; } }

		private readonly CallbackController<NoteOffMessage> _noteOffController = new CallbackController<NoteOffMessage>();
		internal CallbackController<NoteOffMessage> NoteOffController { get { return _noteOffController; } }

		private readonly CallbackController<ControlChangeMessage> _controlChangeController = new CallbackController<ControlChangeMessage>();
		internal CallbackController<ControlChangeMessage> ControlChangeController { get { return _controlChangeController; } }

		private void Ctor()
		{
			_midi.OnMessage += OnMidiMessage;			
		}

		public void HandleMessage(EnsembleStoppedMessage message)
		{
			_callbackControllerCache.Clear();
			_noteOnController.Clear();
			_noteOffController.Clear();
			_controlChangeController.Clear();
		}

		public void OnNoteOn(NoteOnMessage args)
		{
			_callbackControllerCache.Store(args, _noteOnController);
		}

		public void OnNoteOff(NoteOffMessage args)
		{
			_callbackControllerCache.Store(args, _noteOffController);
		}

		public void OnControlChange(ControlChangeMessage args)
		{
			_callbackControllerCache.Store(args, _controlChangeController);
		}

		public void Raise()
		{
			_callbackControllerCache.Raise();
		}

		private void OnMidiMessage(MidiMessage midiMessage)
		{
			if (midiMessage is NoteOnMessage)
			{
				OnNoteOn((NoteOnMessage)midiMessage);
			}
			else if (midiMessage is NoteOffMessage)
			{
				OnNoteOff((NoteOffMessage)midiMessage);
			}
			else if (midiMessage is ControlChangeMessage)
			{
				OnControlChange((ControlChangeMessage)midiMessage);
			}
		}

		public void Dispose()
		{
			_midi.OnMessage -= OnMidiMessage;
		}
	}
}
